// +build !no_check_ptrace

package exploit

import (
	"github.com/cdk-team/CDK/pkg/plugin"
	"github.com/cdk-team/CDK/pkg/tool/ps"
	"io/ioutil"
	"log"
	"regexp"
	"strconv"
)

const sysPtraceCapMask uint64 = 2 << 18

func enableSysPtraceCap(mask uint64) bool {
	return mask&sysPtraceCapMask != 0
}

func CheckPidInject() bool {
	data, err := ioutil.ReadFile("/proc/self/status")
	if err != nil {
		log.Println(err)
		return false
	}

	pattern := regexp.MustCompile("(?i)capeff:\\s*?([a-z0-9]+)\\s")
	params := pattern.FindAllStringSubmatch(string(data), 1)

	for _, matched := range params {
		mask, err := strconv.ParseUint(matched[1], 16, 64)
		if err != nil {
			log.Println(err)
			return false
		}
		if enableSysPtraceCap(mask) {
			log.Println("SYS_PTRACE capability was enabled.")
			ps.RunPs()
			return true
		} else {
			log.Println("SYS_PTRACE capability was disabled.")
			return false
		}
	}
	return false
}

// plugin interface
type PidInject struct{}

func (p PidInject) Desc() string {
	return "check if pid injection works with cap=SYS_PTRACE. usage: ./cdk run check-ptrace"
}
func (p PidInject) Run() bool {
	CheckPidInject()
	return true
}

func init() {
	exploit := PidInject{}
	plugin.RegisterExploit("check-ptrace", exploit)
}